package cn.tedu.charging.order.rabbitmq;

import cn.tedu.charging.order.config.RabbitMQConfig;
import cn.tedu.charging.order.dao.repository.OrderRepository;
import cn.tedu.charging.order.pojo.po.OrderMQPO;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * rabbit-mq 消费者 消费的是死信队列
 */
@Slf4j
@Component
public class RabbitMQOrderConsumer {
    @Resource
    private OrderRepository orderRepository;

    @RabbitListener(queues = RabbitMQConfig.ORDER_DEAD_LETTER_QUEUE)
    public void orderDeadLetter(OrderMQPO orderMQPO, Message message, Channel channel) throws Exception {
        log.info("Order dead letter queue:{}",orderMQPO);
        //如何保证消息不丢失 ? 发的时候不丢,queue和Exchange 开启持久化,手动ack
        //消息队列中的ack是什么意思?
        //消费者 拿到消息,处理业务 更新订单状态
        // 正常情况
        // 更新订单状态成功 ,返回ack给消息队列,
        // 消息队列收到ack后,认为你是消费成功了,会把这个条消息从消息队列删除,消费者继续消费下一条消息
        // 异常情况
        // 数据库出现异常，更新失败，不返回ack给消息队列,
        // 消息队列没有收到ack,认为消费不成功,不会把消息从消息队列删除,消息队列会把这条消息一直保存
        //等我数据库修好了继续重复消费者条消息,数据没丢,继续更新订单的状态

        //把正在充电中的订单状态改为异常结束
        //条件 orderNo,bill_status = 1 结果 bill_status 1 ==> 3
        //two to 2

        orderRepository.updateOrderStatusFromProcess2ExceptionEnd(orderMQPO.getOrderNo());

        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        /*
        * channel.basicAck(deliveryTag, true); 这行代码是在使用RabbitMQ（一个流行的开源消息代理和队列服务器）的Java客户端库时可能遇到的。
        * 这行代码的作用是对RabbitMQ中的消息进行确认（acknowledgment），告诉RabbitMQ该消息已经被消费者成功处理，可以从队列中安全地删除了。
        * 这是RabbitMQ消息确认机制的一部分，用于确保消息不会丢失，即使在消费者处理消息时发生故障也能被重新处理。
        * */
        channel.basicAck(deliveryTag,true);
    }
}
